/**
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-09-C-0002, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * (c) 2009 The MITRE Corporation. All Rights Reserved.
 *
 * SPMIF to OPNET Translator
 * Author: ewalters
 * Created: 2:02:01 PM, Aug 3, 2007
 * MITRE Corporation
 */
package com.mitre.spmif2opnet.analysis;

import javax.xml.bind.JAXBException;

import com.mitre.spmif2opnet.XMLInterface;
import com.mitre.spmif2opnet.analysis.ast.Project;
import com.mitre.spmif2opnet.analysis.ast.Scenario;
import com.mitre.spmif2opnet.spmif.ProjectType;

/**
 * Symbol representing a sync destination
 * We distinguish these because their semantics are different
 */
public class SyncSymbol extends Symbol {
	/**
	 * What is the partner scenario?
	 */
	private Scenario   _partner;
	/**
	 * What is the partner identifier?
	 */
	private Identifier _partner_id;
	/**
	 * What is the name of the partner?
	 */
	private String     _partner_name;
	  
	/**
	 * Default constructor
	 * @param id the id of >this< symbol
	 * @param pname
	 * @param partner_id
	 */
	public SyncSymbol(Identifier id, String pname, Identifier partner_id) {
		super(id);
		_partner = null;
		_partner_name = pname;
		_partner_id = partner_id;
	}
	
	/**
	 * Partner accessor 
	 * @return the partner
	 */
	public Scenario getPartner() {
		return _partner;
	}
	
	/**
	 * Partner mutator
	 * @param p the partner
	 */
	public void setPartner(Scenario p) {
		_partner = p;
	}
	
	/**
	 * Partner name
	 * @return the name
	 */
	public String getPartnerName() {
		return _partner_name;
	}
	
	/**
	 * Has the symbol been resolved, i.e. do we know the partner?
	 */
	public boolean isResolved() {
		return (_partner != null);
	}

	/**
	 * Resolve the symbol using the given analysis context
	 *	Important info for a partner: partner scenario file, scenario name, node name
	 *  We build up the rest of the partner Id as we go
	 * @param c the context
	 */
	public void resolve(AnalysisContext c) {
		if (this.isResolved()) return;
		String scen_file = _partner_id.getFileName();
		String proj_name = this.getId().getProjectName();

		// If this link is from a project that hasn't been loaded, do this!
		if (_partner_id.validFileName() && !c.isFileLoaded(scen_file)) {  
			c.setFileName(scen_file);
			// Load the project from XML dynamically
			try {
				ProjectType ptype = (new XMLInterface()).loadXMLFile(scen_file);
				(new GraphBuilder()).buildGraph(ptype, c);
			} catch (JAXBException exc) {
				System.out.println("[ERROR] [SyncSymbol.resolve] " + this.getId().toString() + " referencing unknown file!");
				System.exit(-1);			
			}
		}
						
		try {
			Project p = c.getProject(proj_name);
			if (p == null) {
				System.out.println("[ERROR] [SyncSymbol.resolve] " + _partner_id.toString() + " referencing unloaded project!");
				System.exit(-1);
			}
			Scenario scen = p.getScenario(_partner_id.getScenarioName());
			_partner_id.setProjectName(p.getName());
			_partner = scen;
		} catch (AnalysisException exc) {
			System.out.println("[ERROR] [SyncSymbol.resolve] " + exc.getMessage());
			System.exit(-1);
		}
		
		// Union the graphs of both ends of the synchronization, since OPNET can't handle 
		//  cross-task messages
		c.getPartitions().unionIds(this.getId(), _partner_id);
		
		return;		
	}
}
